package com.gaojinqi.sys.core.auth.util;

import com.alibaba.fastjson.JSON;
import com.gaojinqi.base.common.exception.AuthException;
import com.gaojinqi.base.core.util.HttpContext;
import com.gaojinqi.sys.common.constant.ShiroDefaultConst;
import com.gaojinqi.sys.core.shiro.util.JwtTokenHelper;
import com.gaojinqi.sys.core.shiro.util.UserCacheHelper;
import com.gaojinqi.sys.modular.rbac.model.LoginBo;
import com.google.common.collect.Lists;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;

/**
 * 登录上下文 shiro 实现
 *
 * @author gaojinqi
 * @version 1.0
 * @since 2020年04月21日
 */
@Component
public class LoginContextShiroSubjectImpl implements LoginContext {

    @Autowired
    private List<Realm> realms;
    @Autowired
    private JwtTokenHelper jwtTokenHelper;
    @Autowired(required = false)
    private UserCacheHelper userCacheHelper;

    private ThreadLocal<LoginBo> threadLocal = new ThreadLocal<>();

    @Override
    public void set(Object user) {
        if (user instanceof LoginBo) {
            threadLocal.set((LoginBo) user);
        } else {
            threadLocal.set(JSON.parseObject(JSON.toJSONString(user), LoginBo.class));
        }
    }

    @Override
    public LoginBo getUser() {
        LoginBo loginBo = threadLocal.get();
        if (loginBo == null) {
            throw new AuthException();
        }
        return loginBo;
        /*Object principal = getSubject().getPrincipal();
        if (principal == null) {
            throw new AuthException();
        }
        return (User) principal;*/
    }

    @Override
    public String getToken() {
        return jwtTokenHelper.getTokenCache(this.getUserName());
    }

    @Override
    public boolean hasLogin() {
        return getSubject().isAuthenticated();
    }

    @Override
    public String getUserId() {
        return getUser().getUserId();
    }

    @Override
    public String getUserName() {
        return getUser().getUserName();
    }

    @Override
    public boolean hasRole(String roleName) {
        return getSubject().hasRole(roleName);
    }

    @Override
    public boolean hasAnyRoles(Collection<String> roleNames) {
        boolean[] hasRoles = getSubject().hasRoles(Lists.newArrayList(roleNames));
        for (boolean hasRole : hasRoles) {
            if (hasRole) {
                return hasRole;
            }
        }
        return false;
    }

    @Override
    public boolean hasAllRoles(Collection<String> roleNames) {
        return getSubject().hasAllRoles(roleNames);
    }

    @Override
    public boolean hasPermission(String permission) {
        return getSubject().isPermitted(permission);
    }

    @Override
    public boolean isAdmin() {
        return false;
    }

    @Override
    public void logout() {
        Subject subject = getSubject();
        String userName = this.getUserName();
        subject.logout();
        // 移除缓存中的jwt
        if (jwtTokenHelper != null) {
            jwtTokenHelper.removeTokenCache(userName);
        }
        // 清空jwt
        jwtTokenHelper.writeJwt(HttpContext.getResponse(), null, false);
    }

    @Override
    public void clearCache() {
        if (userCacheHelper != null) {
            userCacheHelper.deleteByUserId(this.getUserId());
        }
        /*if (!CollectionUtils.isEmpty(realms)) {
            for (Realm realm : realms) {
                if (realm instanceof JwtRealm) {
                    // 清楚当前用户的缓存
                    ((JwtRealm) realm).clearRealmCache();
                }
            }
        }*/
    }

    private Subject getSubject() {
        return SecurityUtils.getSubject();
    }

}
